package com.example.flowabledemo.service.impl;

import com.example.flowabledemo.common.HttpCode;
import com.example.flowabledemo.common.flowable.ProcessValues;
import com.example.flowabledemo.data.dto.ResponseResult;
import com.example.flowabledemo.data.entity.AaApproval;
import com.example.flowabledemo.data.entity.AaProcess;
import com.example.flowabledemo.data.entity.AaRole;
import com.example.flowabledemo.data.entity.AaUser;
import com.example.flowabledemo.data.mapper.AaProcessMapper;
import com.example.flowabledemo.data.mapper.AaRoleMapper;
import com.example.flowabledemo.data.mapper.AaUserMapper;
import com.example.flowabledemo.data.pojo.SecUser;
import com.example.flowabledemo.data.vo.ApplyLeaveVo;
import com.example.flowabledemo.data.vo.UserInfoVo;
import com.example.flowabledemo.service.FlowableService;
import com.example.flowabledemo.service.UserService;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author linke
 * @date 2020/11/26 22:00
 * @description
 */
@Service
public class UserServiceImpl implements UserService {

  @Autowired
  private AaUserMapper aaUserMapper;
  @Autowired
  private AaRoleMapper aaRoleMapper;
  @Autowired
  private FlowableService flowableService;
  @Autowired
  private AaProcessMapper aaProcessMapper;

  @Override
  public SecUser getUser() {
    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
    return (SecUser) authentication.getPrincipal();
  }

  @Override
  public UserInfoVo getUserInfoVo(String username) {
    return aaUserMapper.getUserInfoVo(username);
  }

  @Override
  public AaUser getUser(String username) {
    return aaUserMapper.getUser(username);
  }

  @Override
  public List<AaRole> getRoles(String username) {
    return aaRoleMapper.getRoles(username);
  }

  @Transactional
  @Override
  public ResponseResult applyLeave(ApplyLeaveVo applyLeaveVo, String status) {
    SecUser user = getUser();
    int count=flowableService.getRunProcessNumber(user.getUsername(),ProcessValues.TYPE_LEAVE);
    if(count>0){
      return new ResponseResult(HttpCode.FAIL,"已经存在请假流程，无法发起申请");
    }
    Date date = new Date();
    String handleUser = null;
    String handleGroup = user.getDepartmentCode();
    Map<String, Object> map = new HashMap<>();
    map.put("description", applyLeaveVo.getDescription());
    map.put("startDate", applyLeaveVo.getStartDate());
    map.put("endDate", applyLeaveVo.getEndDate());
    map.put("title", applyLeaveVo.getTitle());
    map.put("type", applyLeaveVo.getType());

    //采用雪花算法生成唯一id，提交到员工创建，此时是暂存状态
    String businessKey = ProcessValues.generateBusinessKey();
    ProcessInstance processInstance = flowableService.start(ProcessValues.TYPE_LEAVE, businessKey, map);

    AaProcess process = new AaProcess();
    process.setCreateTime(date);
    process.setUsername(user.getUsername());
    process.setProcessStatus(ProcessValues.PROCESS_STATUS_SAVE);//暂存
    process.setProcessType(ProcessValues.TYPE_LEAVE);
    process.setBusinessType(ProcessValues.BUSINESS_TYPE.get("人员流程"));
    process.setHandleUser(handleUser);
    process.setHandleGroup(handleGroup);
    process.setBusinessKey(businessKey);
    process.setProcessId(processInstance.getId());
    process.setProcessName(processInstance.getProcessDefinitionName());//流程名称
    //插入流程记录--1、暂存
    flowableService.addProcess(process);
    if (status.equals(ProcessValues.STATUS_SAVE)) {
      return new ResponseResult(HttpCode.OK, "暂存成功！", process.getProcessId());
    }

    //提交到部门让上级经理处理
    //流程参数：
    map.clear();
    map.put("handleGroup", handleGroup);//用于查询，赋予可处理部门即可
    map.put("handleUser", handleUser);//指定处理人，不指定
    map.put("userAction", 1);//1、申请,0、撤销
    Task task = flowableService.getNewestTask(process.getProcessId());
    flowableService.addCommand(task.getId(), processInstance.getId(), "发起请假");
    flowableService.complete(task.getId(), map);
    //更新流程记录--2、发起
    flowableService.updateProcessStatus(process.getProcessId(), ProcessValues.PROCESS_STATUS_RUN);//流程中
    AaApproval aaApproval = new AaApproval();
    aaApproval.setDepartmentCode(user.getDepartmentCode());
    aaApproval.setTaskId(task.getId());
    aaApproval.setCreateTime(date);
    aaApproval.setStatus(ProcessValues.APPROVAL_STATUS_START);
    aaApproval.setUsername(user.getUsername());
    aaApproval.setRemarks("发起请假");
    aaApproval.setProcessId(process.getProcessId());
    //添加初始化审批记录
    flowableService.addApproval(aaApproval);
    return new ResponseResult(HttpCode.OK, "申请提交成功！", process.getProcessId());
  }

  @Transactional
  @Override
  public ResponseResult editLeave(String processInstanceId, String status, ApplyLeaveVo applyLeaveVo, String processRemarks) {
    Map<String, Object> map = new HashMap<>();
    //1、暂存数据的提交操作 1
    if (ProcessValues.STATUS_SUBMIT.equals(status)) {
      AaProcess aaProcess=flowableService.getProcess(processInstanceId);
      if(aaProcess!=null && !ProcessValues.PROCESS_STATUS_SAVE.equals(aaProcess.getProcessStatus())){
        return new ResponseResult(HttpCode.FAIL,"该流程不属于暂存流程，提交失败");
      }
      SecUser user = getUser();
      Date date = new Date();
      String handleUser = null;
      String handleGroup = user.getDepartmentCode();
      //提交到部门让上级经理处理
      //流程参数：
      map.put("handleGroup", handleGroup);//用于查询，赋予可处理部门即可
      map.put("handleUser", handleUser);//指定处理人，不指定
      map.put("userAction", 1);//1、申请,0、撤销
      Task task = flowableService.getNewestTask(processInstanceId);
      flowableService.addCommand(task.getId(), processInstanceId, "发起请假");
      flowableService.complete(task.getId(), map);
      //更新流程记录--2、发起
      flowableService.updateProcessStatus(processInstanceId, ProcessValues.PROCESS_STATUS_RUN);//流程中
      AaApproval aaApproval = new AaApproval();
      aaApproval.setDepartmentCode(user.getDepartmentCode());
      aaApproval.setTaskId(task.getId());
      aaApproval.setCreateTime(date);
      aaApproval.setStatus(ProcessValues.APPROVAL_STATUS_START);
      aaApproval.setUsername(user.getUsername());
      aaApproval.setRemarks("发起请假");
      aaApproval.setProcessId(processInstanceId);
      //添加初始化审批记录
      flowableService.addApproval(aaApproval);
      return new ResponseResult(HttpCode.OK, "申请提交成功！", processInstanceId);

    }
    map.put("description", applyLeaveVo.getDescription());
    map.put("startDate", applyLeaveVo.getStartDate());
    map.put("endDate", applyLeaveVo.getEndDate());
    map.put("title", applyLeaveVo.getTitle());
    map.put("type", applyLeaveVo.getType());
    Task task = flowableService.getNewestTask(processInstanceId);
    //2、暂存数据的更新操作，更新数据即可0
    if (ProcessValues.STATUS_SAVE.equals(status)) {
      AaProcess aaProcess=flowableService.getProcess(processInstanceId);
      if(aaProcess!=null && !ProcessValues.PROCESS_STATUS_SAVE.equals(aaProcess.getProcessStatus())){
        return new ResponseResult(HttpCode.FAIL,"该流程不属于暂存流程，保存失败");
      }
      flowableService.updateMap(processInstanceId, map);
      return new ResponseResult(HttpCode.OK, "更新成功！");
    } else {
      //3、已经存在流程的数据更新操作2
      //添加备注
      flowableService.addCommand(task.getId(), processInstanceId, processRemarks);
      flowableService.complete(task.getId(), map);
      flowableService.updateProcessStatus(processInstanceId, ProcessValues.PROCESS_STATUS_RUN);
      SecUser user = getUser();
      AaApproval aaApproval = new AaApproval();
      aaApproval.setDepartmentCode(user.getDepartmentCode());
      aaApproval.setTaskId(task.getId());
      aaApproval.setCreateTime(new Date());
      aaApproval.setStatus(ProcessValues.APPROVAL_STATUS_AGAIN);
      aaApproval.setUsername(user.getUsername());
      aaApproval.setRemarks("再次发起请假");
      aaApproval.setProcessId(processInstanceId);
      //添加初始化审批记录
      flowableService.addApproval(aaApproval);
      return new ResponseResult(HttpCode.OK, "提交成功！");
    }
  }
}
